package com.nulldev.util.web.HttpServer3;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.Map;
import java.util.TreeMap;

import com.nulldev.util.VariableAPI.MathUtil;
import com.nulldev.util.data.Sets.DataTriplet;
import com.nulldev.util.io.IOUtils;
import com.nulldev.util.networking.misc.SocketUtil;
import com.nulldev.util.web.HttpServer3.MicroCache.CachedPage;
import com.nulldev.util.web.HttpServer3.legacyPages.v1.HttpPage;
import com.nulldev.util.web.HttpServer3.legacyPages.v1.RequestType;
import com.nulldev.util.web.HttpServer3.legacyPages.v2.HttpPage2;
import com.nulldev.util.web.HttpServer3.pages.v3.HttpPage3;
import com.nulldev.util.web.HttpServer3.pages.v3.RequestProtocolType;

/**
 * This is a placeholder interface.
 * 
 * @author null
 * @since 3.0
 */
public interface Page {
	// placeholder class, as well as a interface

	final TreeMap<String, String> LEGACY_LOCKED_COMPAT = new TreeMap<String, String>() {
		private static final long serialVersionUID = 1L;

		public String put(final String key, final String value) {
			return null;
		}

		public void putAll(final java.util.Map<? extends String, ? extends String> map) {
		}

		public String putIfAbsent(final String key, final String value) {
			return null;
		}
	};

	default String pc_get_uuid() {
		return MathUtil.toHex(hashCode());
	}

	@SuppressWarnings("resource")
	public static Response do_response(final RequestType type, final String[] request, final ReadRequest rr, final HttpServer server, final Socket socket,
			final Map<String, String> headers, final Page page) throws IOException {
		if (page instanceof HttpPage3) {
			return ((HttpPage3) page).onRequest(new HttpPage3.Request(request[1], rr.hasStream() ? rr.stream() : HttpPage3.BLANK_IO_STREAM,
					SocketUtil.getIPHostName(socket.getRemoteSocketAddress()), RequestProtocolType.HTTP_1_1).importHeaders(headers).setRequestType(type));
		} else if (page instanceof HttpPage2) {
			final byte[] extraData = rr.hasStream() ? IOUtils.toByteArray(rr.stream()) : null;
			return new Response(
					((HttpPage2) page).request(type, request[1], rr.headers_legacy(), extraData, SocketUtil.getIPHostName(socket.getRemoteSocketAddress())));
		} else if (page instanceof HttpPage) {
			final HttpPage p = ((HttpPage) page);
			if (p.isOverBytes()) {
				return new Response(new DataTriplet<Integer, InputStream, Map<String, String>>(200,
						new ByteArrayInputStream(p.handleRequest_Alt(request[1], SocketUtil.getIPHostName(socket.getRemoteSocketAddress()), type)),
						LEGACY_LOCKED_COMPAT));
			} else if (p.sendRaw()) {
				return new Response(new DataTriplet<Integer, InputStream, Map<String, String>>(200, new FileInputStream(p.getPath()), LEGACY_LOCKED_COMPAT));
			} else {
				return new Response(new DataTriplet<Integer, InputStream, Map<String, String>>(200,
						new ByteArrayInputStream(p.handleRequest(request[1], SocketUtil.getIPHostName(socket.getRemoteSocketAddress()), type).getBytes()),
						LEGACY_LOCKED_COMPAT));
			}
		} else if (page instanceof CachedPage) {
			final CachedPage cp = (CachedPage) page;
			return new Response(200, cp, cp);
		} else {
			return null;
		}
	}
}
